This example used in this tutorial comes from Scoop example computation of pi. We will use a Monte-Carlo method to compute the value of pi.
As written in the Scoop documentation, it spawns two pseudo-random numbers that are fed to the hypot function which calculates the hypotenuse of its parameters. This step computes the Pythagorean equation ($\sqrt{x^2+y^2}$) of the given parameters to find the distance from the origin (0,0) to the randomly placed point (which X and Y values were generated from the two pseudo-random values). Then, the result is compared to one to evaluate if this point is inside or outside the unit disk. If it is inside (have a distance from the origin lesser than one), a value of one is produced (red dots in the figure), otherwise the value is zero (blue dots in the figure). The experiment is repeated tries number of times with new random values.
We will use function for the math
library to test if a couple of numbers is inside the unit disk. The mathematical function corresponds to $\sqrt{x^2+y^2}<1$. The evaluation of $\pi$ will correspond to $4*\frac{I}{t}$ where:
The Python functions can be written like this:
In [2]:
from math import hypot
# Test if point p(x, y) is inside the unit disk
# Returns: True if inside, False if outside
def test(p):
return hypot(p[0], p[1]) < 1
# Returns estimated pi value of an experiment
def compute_pi(i, t):
return 4.0*i/t
Now let's try this function on some obvious values. We will define an evaluate
function that take all elements of the list and test if it is inside or outside the unit disk
In [79]:
# Evaluates a list of values passed as an argument
# returns 2 lists:
# * inside: values inside the disk
# * outside: values outside the disk
def evaluate(test_values):
inside = []
outside = []
for p in test_values:
if test(p):
inside.append(p)
else:
outside.append(p)
return inside, outside
range25 = [i/100.0 for i in range(0, 101, 25)]*5
test_values = zip(range25, sorted(range25))
inside, outside = evaluate(test_values)
print("inside: %s" % inside)
print("outside: %s" % outside)
estimate_pi = compute_pi(len(inside),len(test_values))
print("pi = %f" % estimate_pi)
We can plot the results using matplotlib. We will define a plot_points
function that will plot the points on a grid with:
In [80]:
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.patches import Wedge
# Plots points on a grid
# Takes list of points that are inside and points that are outside
def plot_points(inside, outside, alpha=0.3):
fig, ax = plt.subplots()
circle = Wedge((0, 0), 1, 0, 90, color='gray', alpha=0.2)
ax.add_patch(circle)
ax.scatter([p[0] for p in inside], \
[p[1] for p in inside], \
c='red', label='inside', alpha=alpha)
ax.scatter([p[0] for p in outside], \
[p[1] for p in outside], \
c='blue', label='outside', alpha=alpha)
ax.legend()
ax.axes.set_aspect('equal')
ax.grid(True)
plt.show()
plot_points(inside, outside, alpha=1)
Let's generate a lot of random values using random
function.
In [81]:
from random import random
test_values = [(random(), random()) for p in range(1000)]
inside, outside = evaluate(test_values)
plot_points(inside, outside)
estimate_pi = compute_pi(len(inside),len(test_values))
print("pi = %f" % estimate_pi)
Let's do the same using numpy
and a lot more value.
In [82]:
import numpy as np
test_values = np.random.rand(30000, 2)
i = np.sum(map(test, test_values))
estimate_pi = compute_pi(float(i),float(len(test_values)))
print("pi = %f" % estimate_pi)
In [64]:
In [ ]: